package gnetty

import (
	"gitee.com/llakcs/gnetty/commom"
	"gitee.com/llakcs/gnetty/config"
	"github.com/panjf2000/ants/v2"
	"log"
	"net"
)

type ClientConn struct {
	Conf *config.ClientConf
	Conn *net.TCPConn
}

//新建连接
func NewConn(conf *config.ClientConf) *ClientConn {
	return &ClientConn{
		Conf: conf,
		Conn: nil,
	}
}

//单个连接
func (c *ClientConn) Connect() {
	addr, _ := net.ResolveTCPAddr("tcp4", c.Conf.Addr)
	//建立tcp连接
	conn, err := net.DialTCP("tcp4", nil, addr)
	if err != nil {
		return
	}
	if c.Conf.ChanSize == 0 {
		c.Conf.ChanSize = 1024
	}
	//io线程通道
	iochan := make(chan *commom.ChannelContext, c.Conf.ChanSize)
	c.Conn = conn
	ants.Submit(func() {
		//创建channelContext
		ctx := &commom.ChannelContext{
			Conn:     conn,
			DecodeH:  c.Conf.DecoderHandler,
			EncodeH:  c.Conf.EncodeHandler,
			ChannelH: c.Conf.ChanReadHandler,
			Buf:      nil,
		}
		handleClientConn(ctx, c.Conf.ChanSize, iochan)
	})
	handlerClientIo(iochan)
}

func handlerClientIo(iochan chan *commom.ChannelContext) {
	go func() {
		for {
			select {
			case ctx := <-iochan:
				ants.Submit(func() {
					ctx.DecodeH(ctx)
				})
			}
		}
	}()
}

func handleClientConn(ctx *commom.ChannelContext, buffsize int, iochan chan *commom.ChannelContext) {
	buf := make([]byte, buffsize) //设置读取数据缓冲区
	defer ctx.Conn.Close()        // close connection before exit
	for {
		read_len, err := ctx.Conn.Read(buf) //读取客户端发来的数据
		if read_len == 0 {
			err = &commom.ReadLenError{}
		}
		if err != nil {
			log.Println("##连接发生异常，remote addr:", ctx.Conn.RemoteAddr(), "异常原因:", err)
			//stores := engine.GetEngine().StoreMap
			//for _, v := range stores {
			//	if v.Conn.RemoteAddr() == conn.RemoteAddr() {
			//		logcat.GetLog().Sugar().Info("###id:", v.StoreID, "已离线")
			//		//设置离线
			//		v.SetAlive(false)
			//	}
			//}
			return
		}
		ctx.Buf = buf[:read_len]
		//发送到io线程池
		iochan <- ctx
	}
}
